package com.hgyc.mom.common.service.impl;

import com.hgyc.mom.common.config.FileProperties;
import com.hgyc.mom.common.exception.file.FileException;
import com.hgyc.mom.common.service.FileServiceStrategy;
import com.hgyc.mom.common.util.file.FileUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.nio.file.*;

/**
 * 本地文件服务
 * @author fwj
 * @since 2025/4/24
 */
@Slf4j
@Service
@ConditionalOnProperty(name = "mom.upload.strategy", havingValue = "local")
public class LocalFileServiceImpl implements FileServiceStrategy {

    @Autowired
    private FileProperties properties;

    @Override
    public String uploadFile(MultipartFile file) throws FileException {
        try {
            return FileUtils.upload(properties.getUploadPath(), file);
        } catch (IOException e) {
            throw new FileException("文件上传失败", e);
        }
    }

    @Override
    public String uploadFile(MultipartFile file, String folder) throws FileException {
        try {
            return FileUtils.upload(properties.getUploadPath()+ File.separator + folder, file);
        } catch (IOException e) {
            log.error("文件上传失败", e);
            throw new FileException("文件上传失败", e);
        }
    }

    @Override
    public byte[] downloadFile(String filePath) throws FileException {
        // 参数校验
        if (filePath == null || filePath.trim().isEmpty()) {
            throw new FileException("文件路径不能为空");
        }

        // 路径处理
        Path fullPath;
        try {
            fullPath = Paths.get(properties.getUploadPath(), filePath).normalize();
        } catch (InvalidPathException e) {
            throw new FileException("无效的文件路径: " + filePath, e);
        }

        // 资源加载和校验
        UrlResource resource;
        try {
            resource = new UrlResource(fullPath.toUri());
        } catch (MalformedURLException e) {
            throw new FileException("无效的文件URL路径: " + fullPath, e);
        }

        if (!resource.exists()) {
            throw new FileException("文件不存在: " + fullPath);
        }
        if (!resource.isReadable()) {
            throw new FileException("文件不可读: " + fullPath);
        }

        // 读取文件内容
        try (InputStream inputStream = resource.getInputStream()) {
            return inputStream.readAllBytes();
        } catch (IOException e) {
            throw new FileException("读取文件失败: " + fullPath, e);
        }
    }

    @Override
    public void deleteFile(String filePath) throws FileException {
        // 参数校验
        if (filePath == null || filePath.trim().isEmpty()) {
            throw new IllegalArgumentException("文件路径不能为空或空字符串");
        }

        // 路径处理和安全检查
        Path fullPath;
        try {
            fullPath = Paths.get(properties.getUploadPath(), filePath).normalize();

            // 安全验证：确保目标路径在基础目录内
            if (!fullPath.startsWith(Paths.get(properties.getUploadPath()).normalize())) {
                throw new FileException("非法文件路径: 尝试访问外部目录");
            }
        } catch (InvalidPathException e) {
            throw new FileException("无效的文件路径: " + filePath, e);
        }

        // 执行删除
        try {
            boolean deleted = Files.deleteIfExists(fullPath);
            if (!deleted) {
                log.warn("文件不存在，无需删除: {}", fullPath);
            }
        } catch (NoSuchFileException e) {
            log.warn("文件不存在，无需删除: {}", fullPath);
        } catch (AccessDeniedException e) {
            throw new FileException("无权限删除文件: " + fullPath, e);
        } catch (DirectoryNotEmptyException e) {
            throw new FileException("无法删除非空目录: " + fullPath, e);
        } catch (SecurityException e) {
            throw new FileException("安全限制阻止文件删除: " + fullPath, e);
        } catch (IOException e) {
            throw new FileException("删除文件失败: " + fullPath, e);
        }
    }
}
